# -*- coding: utf-8 -*-
"""
中性策略框架 | 邢不行 | 2024分享会
author: 邢不行
微信: xbx6660
"""
import os
import sys
import pandas as pd
from Functions import *
from joblib import Parallel, delayed, dump
from matplotlib import pyplot as plt
import time
from tqdm import tqdm
import ast
from Config import *

plt.rcParams['figure.figsize'] = [12, 6]
plt.rcParams['font.sans-serif'] = ['SimHei', 'Arial Unicode MS', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False

# 动态读取config里面配置的strategy_name脚本
Shift = __import__('shift.%s' % shift_name, fromlist=('',))
# 从Shift中取出 回测持仓周期hold_period
hold_period = Shift.hold_period
# 从Shift中取出 策略名offset
offset = Shift.offset

# 获取当前环境下的python解释器
python_exec = sys.executable


def ergodic_back_test(info):
    offset = info[0]
    factor_col = info[1]
    if_ascending = info[2]
    select_num = info[3]
    os.system(f'%s "{root_path}/program/1_轮动策略回测.py" %s %s %s %s %s' % (python_exec, offset, factor_col, if_ascending, select_num, save_path))


if __name__ == '__main__':
    # 运行前需要将因子对应的参数整理好
    # 运行前需要把之前遍历保存下来的数据删掉，或者改个文件名

    # =====遍历回测的准备
    # 设定想遍历的因子
    ratation_factor = 'BiasMean'  # 只支持单因子

    # 设定想遍历的因子参数
    #factor_param_list = range(2, 31, 1)
    factor_param_list = range(150, 800, 5)

    # 设定想遍历的因子排序方式
    if_ascending = False

    # 设定想遍历的选策略数量
    select_num = 1

    # 设定保存文件的路径
    # 设定文件保存的路径
    save_path = os.path.join(root_path, 'data/回测结果/轮动回测结果汇总_参数平原图.csv')

    infos = []
    for param in factor_param_list:
        select_factor = ratation_factor + '_' + str(param)
        infos.append([offset, select_factor, if_ascending, select_num])

    # =====并行或串行，依次调用2号脚本
    multiply_process = True  # 是否并行。在测试的时候可以改成False，实际跑的时候改成True
    if multiply_process:
        df_list = Parallel(n_jobs=n_jobs)(delayed(ergodic_back_test)(info) for info in tqdm(infos))
    else:
        for info in tqdm(infos):
            ergodic_back_test(info)

    # 读取保存的数据
    if not os.path.exists(save_path):
        print(f'参数平原计算统计结果不存在，请检查当前遍历配置信息是否正确 或【{back_test_path}】目录下是否存在文件')
        exit()
    result = pd.read_csv(save_path, encoding='gbk')
    result = result.drop_duplicates().reset_index(drop=True)
    result = result.dropna(axis=0).reset_index(drop=True)
    result = result[(result['持仓周期'] == hold_period) & (result['offset'] == offset) & (result['选策略数量'] == select_num)]
    result['参数'] = result['因子'].apply(lambda x: int(x.split(',')[2].strip()))
    result['排序方式'] = result['因子'].apply(lambda x: eval(x.split(',')[1].strip()))
    result['因子'] = result['因子'].apply(lambda x: x.split("'")[1])
    result = result[(result['因子'] == ratation_factor) & (result['排序方式'] == if_ascending) & (result['参数'].isin(factor_param_list))]

    # 转换数据格式
    result['累积净值'] = result['累积净值'].map(lambda x: float(x))
    years = list(range(int(start_date.split('-')[0]), int(end_date.split('-')[0]) + 1, 1))
    result['各年收益'] = result['各年收益'].apply(ast.literal_eval)
    for i, year in enumerate(years):
        result[year] = result['各年收益'].map(lambda x: (x[i]) / 100 + 1)
    result['换仓次数'] = result['换仓次数'].map(lambda x: int(x))

    # 画历年参数平原图
    fig, axs = plt.subplots(nrows=len(years) + 2, ncols=1)
    if_xticks = True if len(result['参数']) <= 30 else False
    xticks = result['参数'].to_list()
    x_tick_labels = [f'{t}' for t in xticks]
    axs[0].bar(result['参数'], result['累积净值'], width=0.5)
    axs[0].set_title('累计净值')
    if if_xticks:
        axs[0].set_xticks(xticks)
        axs[0].set_xticklabels(x_tick_labels)
    for index, year in enumerate(years):
        axs[index + 1].bar(result['参数'], result[year], width=0.5)
        axs[index + 1].set_title(f'{year}')
        if if_xticks:
            axs[index + 1].set_xticks(xticks)
            axs[index + 1].set_xticklabels(x_tick_labels)
    axs[len(years) + 1].bar(result['参数'], result['换仓次数'], width=0.5)
    axs[len(years) + 1].set_title('换仓次数')
    if if_xticks:
        axs[len(years) + 1].set_xticks(xticks)
        axs[len(years) + 1].set_xticklabels(x_tick_labels)
    for label, height in zip(result['参数'], result['换仓次数']):
        plt.text(label, height, str(height), ha='center', va='bottom')
    plt.suptitle('历年参数平原图')
    plt.tight_layout()
    plt.show()
